package org.example.springboot.common.utils;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import com.xxl.job.core.biz.model.XxlJobGroup;
import com.xxl.job.core.biz.model.XxlJobInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.net.HttpCookie;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Component
public class XxlJobUtil {

    private String adminAddresses = "";

    private String appname = "";

    private RestTemplate restTemplate = new RestTemplate();

    private static final String ADD_URL = "/jobinfo/addJob";

    private static final String UPDATE_URL = "/jobinfo/updateJob";

    private static final String REMOVE_URL = "/jobinfo/removeJob";

    private static final String REMOVE_CONDITION_URL = "/jobinfo/removeByCondition";

    private static final String PAUSE_URL = "/jobinfo/pauseJob";

    private static final String START_URL = "/jobinfo/startJob";

    private static final String ADD_START_URL = "/jobinfo/addAndStart";

    private static final String GET_GROUP_ID = "/jobgroup/getGroupId";

    public String addTask(String appName, XxlJobInfo jobInfo) {
        this.appname = appName;
        return add(jobInfo);
    }

    public String add(XxlJobInfo jobInfo) {
        // 查询对应groupId:
        Map<String, Object> param = new HashMap<>();
        param.put("appname", appname);
        String json = JSON.toJSONString(param);
        String result = doPost(adminAddresses + GET_GROUP_ID, json);

        JSONObject jsonObject = JSON.parseObject(result);
        String groupId = jsonObject.getString("content");
        jobInfo.setJobGroup(Integer.parseInt(groupId));
        String json2 = JSON.toJSONString(jobInfo);
        return doPost(adminAddresses + ADD_URL, json2);
    }

    public String update(int id, String cron) {
        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        param.put("jobCron", cron);
        String json = JSON.toJSONString(param);
        return doPost(adminAddresses + UPDATE_URL, json);
    }

    public String remove(String adminAddresses, int id) {
        this.adminAddresses = adminAddresses;
        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        String json = JSON.toJSONString(param);
        return doPost(adminAddresses + REMOVE_URL, json);
    }

    public String removeByCondition(String adminAddresses, String jobDesc) {
        this.adminAddresses = adminAddresses;
        Map<String, Object> param = new HashMap<>();
        param.put("jobDesc", jobDesc);
        String json = JSON.toJSONString(param);
        return doPost(adminAddresses + REMOVE_CONDITION_URL, json);
    }

    public String pause(int id) {
        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        String json = JSON.toJSONString(param);
        return doPost(adminAddresses + PAUSE_URL, json);
    }

    public String start(int id) {
        Map<String, Object> param = new HashMap<>();
        param.put("id", id);
        String json = JSON.toJSONString(param);
        return doPost(adminAddresses + START_URL, json);
    }

    public String addAndStartTask(String appName, String adminAddresses, XxlJobInfo jobInfo) {
        this.appname = appName;
        this.adminAddresses = adminAddresses;
        return addAndStart(jobInfo);
    }

    public String addAndStart(XxlJobInfo jobInfo) {
        Map<String, Object> param = new HashMap<>();
        param.put("appname", appname);
        String json = JSON.toJSONString(param);
        String result = doPost(adminAddresses + GET_GROUP_ID, json);

        JSONObject jsonObject = JSON.parseObject(result);
        String groupId = jsonObject.getString("content");
        jobInfo.setJobGroup(Integer.parseInt(groupId));
        String json2 = JSON.toJSONString(jobInfo);

        return doPost(adminAddresses + ADD_START_URL, json2);
    }

    public String doPost(String url, String json) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.put("Cookie", this.getCookie());
        HttpEntity<String> entity = new HttpEntity<>(json, headers);
        log.info(entity.toString());
        ResponseEntity<String> stringResponseEntity = restTemplate.postForEntity(url, entity, String.class);
        return Objects.requireNonNull(stringResponseEntity.getBody());
    }

    //将cookie缓存到本地map中
    private final Map<String, String> loginCookie = new HashMap<>();

    public void login() {
        String url = adminAddresses + "/login";
        HttpResponse response = HttpRequest.post(url)
                .form("userName", "admin")
                .form("password", "123456")
                .execute();
        List<HttpCookie> cookies = response.getCookies();
        Optional<HttpCookie> cookieOpt = cookies.stream()
                .filter(cookie -> cookie.getName().equals("XXL_JOB_LOGIN_IDENTITY")).findFirst();
        if (!cookieOpt.isPresent())
            throw new RuntimeException("get xxl-job cookie error!");

        String value = cookieOpt.get().getValue();
        loginCookie.put("XXL_JOB_LOGIN_IDENTITY", value);
    }

    public List<String> getCookie() {
        for (int i = 0; i < 3; i++) {
            String cookieStr = loginCookie.get("XXL_JOB_LOGIN_IDENTITY");
            if (cookieStr != null) {
                return Collections.singletonList("XXL_JOB_LOGIN_IDENTITY=" + cookieStr);
            }
            login();
        }
        throw new RuntimeException("获取cookie失败!");
    }

    public List<XxlJobGroup> getJobGroup() {
        String url = adminAddresses + "/jobgroup/pageList";
        HttpResponse response = HttpRequest.post(url)
                .form("appname", "")
                .form("title", "")
                .cookie(this.getCookie().get(0))
                .execute();

        String body = response.body();
        JSONArray array = JSONUtil.parse(body).getByPath("data", JSONArray.class);
        return array.stream()
                .map(o -> JSONUtil.toBean((String) o, XxlJobGroup.class))
                .collect(Collectors.toList());
    }

}